//
//  JKBrowserPresentationController.swift
//  JKWeibo
//
//  Created by albert on 16/6/24.
//  Copyright © 2016年 albert. All rights reserved.
//  自定义转场

import UIKit

protocol JKBrowserPresentationControllerDelegate: NSObjectProtocol {
    /** 用于创建一个和点击图片一模一样的UIImageView */
    func browserPresentationControllerWillShowImageView(browserPresentationController: JKBrowserPresentationController, collectionViewCellIndex: NSIndexPath) -> UIImageView
    /** 用于获取点击的图片相对于keyWindow的frame */
    func browserPresentationControllerWillFromFrame(browserPresentationController: JKBrowserPresentationController, collectionViewCellIndex: NSIndexPath) -> CGRect
    /** 用于获取点击图片在图片浏览器中的最终frame */
    func browserPresentationControllerWillToframe(browserPresentationController: JKBrowserPresentationController, collectionViewCellIndex: NSIndexPath) -> CGRect
}

class JKBrowserPresentationController: UIPresentationController {
    /** 定义标记 记录当前是否展现 */
    private var isPresent = false
    
    /** 索引 */
    private var collectionViewCellIndex: NSIndexPath?
    
    /** 代理 */
    weak var browserDelegate: JKBrowserPresentationControllerDelegate?
    
    /** 设置默认数据，因为自己没法直接设置代理，所以让主页控制器帮忙 */
    func setDefaultInfo(index: NSIndexPath, browserDelegate: JKBrowserPresentationControllerDelegate) {

        self.collectionViewCellIndex = index
        self.browserDelegate = browserDelegate
    }
}

extension JKBrowserPresentationController: UIViewControllerTransitioningDelegate {
    // 该方法返回一个负责转场动画的对象
    func presentationControllerForPresentedViewController(presented: UIViewController, presentingViewController presenting: UIViewController, sourceViewController source: UIViewController) -> UIPresentationController?{
        
        // 这是自定义的JKPresentationController
        let pc = JKBrowserPresentationController(presentedViewController: presented, presentingViewController: presenting)
        
        return pc
    }
    
    // 该方法用于返回一个负责转场如何出现的对象
    func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning?{
        
        isPresent = true
        
        //self要遵守UIViewControllerAnimatedTransitioning协议，并实现对应方法
        return self
    }
    
    // 该方法用于返回一个负责转场如何消失的对象
    func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning?{
        
        isPresent = false
        
        //self要遵守UIViewControllerAnimatedTransitioning协议，并实现对应方法
        return self
    }
}

extension JKBrowserPresentationController: UIViewControllerAnimatedTransitioning {
    // 告诉系统展现和消失的动画时长。在这里统一控制动画时长
    func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval{
        
        return 0.25
    }
    
    // 专门用于管理modal如何展现和消失的，无论是展现还是消失都会调用该方法
    func animateTransition(transitionContext: UIViewControllerContextTransitioning){
        
        // 0.判断当前是展现还是消失
        // 注意：消失的时候，toView和fromView已经对换了
        if isPresent {// 展现
            willPresentController(transitionContext)
            
        }else {//消失
            willDismissController(transitionContext)
        }
    }
    
    //MARK: - 执行展现的动画
    private func willPresentController(transitionContext: UIViewControllerContextTransitioning){

        assert(collectionViewCellIndex != nil, "必须设置被点击cell的indexPath")
        assert(browserDelegate != nil, "必须设置代理")
        
        // 1.获取要弹出的视图（图片浏览器）
        // 通过ToViewKey取出来的就是toVc对应的view
        guard let toView = transitionContext.viewForKey(UITransitionContextToViewKey) else{
            return
        }
        
        // 2.1新建一个UIImageView，并且上面显示的内容必须和被点击的图片一模一样
        let imageView = browserDelegate!.browserPresentationControllerWillShowImageView(self, collectionViewCellIndex: collectionViewCellIndex!)
        
        // 2.2获取点击的图片相对于keyWindow的frame，因为容器默认是全屏的，而图片是添加到容器上的，所以必须获取相对于keyWindow的frame
        imageView.frame = browserDelegate!.browserPresentationControllerWillFromFrame(self, collectionViewCellIndex: collectionViewCellIndex!)
        
        // 将新建的UIImageView添加到容器上
        transitionContext.containerView()?.addSubview(imageView)
        transitionContext.containerView()?.backgroundColor = UIColor.blackColor()
        
        // 2.3获取点击的图片在图片浏览器上的最终frame
        let toFrame = browserDelegate!.browserPresentationControllerWillToframe(self, collectionViewCellIndex: collectionViewCellIndex!)
        
        // 3.执行动画
        UIView.animateWithDuration(transitionDuration(transitionContext), animations: { () -> Void in
            
            imageView.frame = toFrame
            
            }) { (_) -> Void in
                // 移除自己创建的UIImageView
                imageView.removeFromSuperview()
                
                // 显示图片浏览器
                transitionContext.containerView()?.addSubview(toView)
                
                // 注意：自定义转场动画，在执行完动画之后一定要告诉系统动画执行完毕了！！
                transitionContext.completeTransition(true)
        }
    }
    
    //MARK: - 执行消失的动画
    private func willDismissController(transitionContext: UIViewControllerContextTransitioning){

        assert(collectionViewCellIndex != nil, "必须设置被点击cell的indexPath")
        assert(browserDelegate != nil, "必须设置代理")
        
        // 1、获取图片浏览器的控制器及其view
        guard let fromView = transitionContext.viewForKey(UITransitionContextFromViewKey) else{
            return
        }
        guard let fromVc = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey) as? JKPicBrowserViewController else{
            return
        }
        
        // 2.获取图片浏览器当前显示图片的索引
        let indexPath = fromVc.collectionView.indexPathsForVisibleItems().last!
        
        // 3.创建和当前显示的图片一模一样的UIImageView
        let imageView = UIImageView()
        // 3.1设置内容模式
        imageView.contentMode = UIViewContentMode.ScaleAspectFill
        imageView.clipsToBounds = true
        // 3.2设置图片
        imageView.image = browserDelegate!.browserPresentationControllerWillShowImageView(self, collectionViewCellIndex: indexPath).image
        // 3.3添加到容器视图
        transitionContext.containerView()?.addSubview(imageView)
        // 3.4设置frame
        imageView.frame = browserDelegate!.browserPresentationControllerWillToframe(self, collectionViewCellIndex: indexPath)
        // 3.5将容器视图的背景设置为透明
        transitionContext.containerView()?.backgroundColor = UIColor.clearColor()
        // 3.6移除图片浏览器的view
        fromView.removeFromSuperview()
        // 3.7获取当前显示图片缩小还原后相对于keyWindow的frame
        let fromFrame = browserDelegate!.browserPresentationControllerWillFromFrame(self, collectionViewCellIndex: indexPath)
        
        // 4.执行动画
        UIView.animateWithDuration(transitionDuration(transitionContext), animations: { () -> Void in
            imageView.frame = fromFrame
            
            }) { (_) -> Void in
                imageView.removeFromSuperview()
                // 注意：自定义转场动画，在执行完动画之后一定要告诉系统动画执行完毕了！！
                transitionContext.completeTransition(true)
        }
    }
}